using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.Xml.XPath;
using System.Collections;

namespace BTS_Utilities.EDI_Fixup.EDISyntax
{
    public static class EDISyntax_837I
    {
        /*
         * We need to renumber the following parent and childitems:
         * (Parent) 1 - [HL_BillingPayToProviderHierarchicalLevel_TS837Q3_2000A] found:
         *   - /*[local-name()='X12EnrichedMessage_X12_00401_837_I' and namespace-uri()='http://schemas.microsoft.com/BizTalk/EDI/X12/2006/EnrichedMessage_X12_00401_837_I']/*[local-name()='TransactionSet' and namespace-uri()='']/*[local-name()='X12_00401_837_I' and namespace-uri()='http://schemas.microsoft.com/BizTalk/EDI/X12/2006']/*[local-name()='TS837Q3_2000A_Loop' and namespace-uri()='http://schemas.microsoft.com/BizTalk/EDI/X12/2006']/*[local-name()='HL_BillingPayToProviderHierarchicalLevel_TS837Q3_2000A' and namespace-uri()='http://schemas.microsoft.com/BizTalk/EDI/X12/2006']/*[local-name()='HL01__HierarchicalIDNumber' and namespace-uri()='']
         * (Parent) 2 - [subscriber HL ID - HL01__HierarchicalIDNumber]
         *   - /*[local-name()='X12EnrichedMessage_X12_00401_837_I' and namespace-uri()='http://schemas.microsoft.com/BizTalk/EDI/X12/2006/EnrichedMessage_X12_00401_837_I']/*[local-name()='TransactionSet' and namespace-uri()='']/*[local-name()='X12_00401_837_I' and namespace-uri()='http://schemas.microsoft.com/BizTalk/EDI/X12/2006']/*[local-name()='TS837Q3_2000A_Loop' and namespace-uri()='http://schemas.microsoft.com/BizTalk/EDI/X12/2006']/*[local-name()='TS837Q3_2000B_Loop' and namespace-uri()='http://schemas.microsoft.com/BizTalk/EDI/X12/2006']/*[local-name()='HL_SubscriberHierarchicalLevel_TS837Q3_2000B' and namespace-uri()='http://schemas.microsoft.com/BizTalk/EDI/X12/2006']/*[local-name()='HL01__HierarchicalIDNumber' and namespace-uri()='']
         * (Child) 2a - HL02__HierarchicalParentIDNumber
         *   - /*[local-name()='X12EnrichedMessage_X12_00401_837_I' and namespace-uri()='http://schemas.microsoft.com/BizTalk/EDI/X12/2006/EnrichedMessage_X12_00401_837_I']/*[local-name()='TransactionSet' and namespace-uri()='']/*[local-name()='X12_00401_837_I' and namespace-uri()='http://schemas.microsoft.com/BizTalk/EDI/X12/2006']/*[local-name()='TS837Q3_2000A_Loop' and namespace-uri()='http://schemas.microsoft.com/BizTalk/EDI/X12/2006']/*[local-name()='TS837Q3_2000B_Loop' and namespace-uri()='http://schemas.microsoft.com/BizTalk/EDI/X12/2006']/*[local-name()='HL_SubscriberHierarchicalLevel_TS837Q3_2000B' and namespace-uri()='http://schemas.microsoft.com/BizTalk/EDI/X12/2006']/*[local-name()='HL02__HierarchicalParentIDNumber' and namespace-uri()='']
         * (Parent) 3 - [patient HL ID - HL_PatientHierarchicalLevel_TS837Q3_2000C]
         *   - /*[local-name()='X12EnrichedMessage_X12_00401_837_I' and namespace-uri()='http://schemas.microsoft.com/BizTalk/EDI/X12/2006/EnrichedMessage_X12_00401_837_I']/*[local-name()='TransactionSet' and namespace-uri()='']/*[local-name()='X12_00401_837_I' and namespace-uri()='http://schemas.microsoft.com/BizTalk/EDI/X12/2006']/*[local-name()='TS837Q3_2000A_Loop' and namespace-uri()='http://schemas.microsoft.com/BizTalk/EDI/X12/2006']/*[local-name()='TS837Q3_2000B_Loop' and namespace-uri()='http://schemas.microsoft.com/BizTalk/EDI/X12/2006']/*[local-name()='TS837Q3_2000C_Loop' and namespace-uri()='http://schemas.microsoft.com/BizTalk/EDI/X12/2006']/*[local-name()='HL_PatientHierarchicalLevel_TS837Q3_2000C' and namespace-uri()='http://schemas.microsoft.com/BizTalk/EDI/X12/2006']/*[local-name()='HL01__HierarchicalIDNumber' and namespace-uri()='']
         * (Child) 3a - [patient parent id HL02__HierarchicalParentIDNumber]
         *   - /*[local-name()='X12EnrichedMessage_X12_00401_837_I' and namespace-uri()='http://schemas.microsoft.com/BizTalk/EDI/X12/2006/EnrichedMessage_X12_00401_837_I']/*[local-name()='TransactionSet' and namespace-uri()='']/*[local-name()='X12_00401_837_I' and namespace-uri()='http://schemas.microsoft.com/BizTalk/EDI/X12/2006']/*[local-name()='TS837Q3_2000A_Loop' and namespace-uri()='http://schemas.microsoft.com/BizTalk/EDI/X12/2006']/*[local-name()='TS837Q3_2000B_Loop' and namespace-uri()='http://schemas.microsoft.com/BizTalk/EDI/X12/2006']/*[local-name()='TS837Q3_2000C_Loop' and namespace-uri()='http://schemas.microsoft.com/BizTalk/EDI/X12/2006']/*[local-name()='HL_PatientHierarchicalLevel_TS837Q3_2000C' and namespace-uri()='http://schemas.microsoft.com/BizTalk/EDI/X12/2006']/*[local-name()='HL02__HierarchicalParentIDNumber' and namespace-uri()='']
         * 
         * pseudo code should look like this:
         * For  each BillingPRovider
         *      Get Unique ID
         *          For each Subscriber
         *              Get Unique ID
         *              Set parent to BillingProviderHL Level
         *                  For each Patient
         *                      Get UniqueID
         *                      Set Parent to Subscriber level
         */
        internal static string getXPathToSubscriberLoop(int billingIterator)
        {
            return @"/*[local-name()='X12_00401_837_I' and namespace-uri()='http://schemas.microsoft.com/BizTalk/EDI/X12/2006']/*[local-name()='TS837Q3_2000A_Loop' and namespace-uri()='http://schemas.microsoft.com/BizTalk/EDI/X12/2006'][" + billingIterator + "]/*[local-name()='TS837Q3_2000B_Loop' and namespace-uri()='http://schemas.microsoft.com/BizTalk/EDI/X12/2006']";
        }

        internal static string getXPathToSubscriberClaims(int subscriberIterator, int billingIterator)
        {
            return @"/*[local-name()='X12_00401_837_I' and namespace-uri()='http://schemas.microsoft.com/BizTalk/EDI/X12/2006']/*[local-name()='TS837Q3_2000A_Loop' and namespace-uri()='http://schemas.microsoft.com/BizTalk/EDI/X12/2006'][" + billingIterator + "]/*[local-name()='TS837Q3_2000B_Loop' and namespace-uri()='http://schemas.microsoft.com/BizTalk/EDI/X12/2006'][" + subscriberIterator + "]/*[local-name()='TS837Q3_2300_Loop' and namespace-uri()='http://schemas.microsoft.com/BizTalk/EDI/X12/2006']";
        }
        internal static string getXPathToSubscriberHL04(int subscriberIterator, int billingIterator)
        {
            return @"/*[local-name()='X12_00401_837_I' and namespace-uri()='http://schemas.microsoft.com/BizTalk/EDI/X12/2006']/*[local-name()='TS837Q3_2000A_Loop' and namespace-uri()='http://schemas.microsoft.com/BizTalk/EDI/X12/2006'][" + billingIterator + "]/*[local-name()='TS837Q3_2000B_Loop' and namespace-uri()='http://schemas.microsoft.com/BizTalk/EDI/X12/2006'][" + subscriberIterator + "]/*[local-name()='HL_SubscriberHierarchicalLevel_TS837Q3_2000B' and namespace-uri()='http://schemas.microsoft.com/BizTalk/EDI/X12/2006']/*[local-name()='HL04__HierarchicalChildCode' and namespace-uri()='']";
        }
        internal static string getXPathToPatientLoop(int subscriberIterator, int billingIterator)
        {
            return @"/*[local-name()='X12_00401_837_I' and namespace-uri()='http://schemas.microsoft.com/BizTalk/EDI/X12/2006']/*[local-name()='TS837Q3_2000A_Loop' and namespace-uri()='http://schemas.microsoft.com/BizTalk/EDI/X12/2006'][" + billingIterator + "]/*[local-name()='TS837Q3_2000B_Loop' and namespace-uri()='http://schemas.microsoft.com/BizTalk/EDI/X12/2006'][" + subscriberIterator + "]/*[local-name()='TS837Q3_2000C_Loop' and namespace-uri()='http://schemas.microsoft.com/BizTalk/EDI/X12/2006']";
        }
        internal static string getXPathToPatientClaims(int subscriberIterator, int billingIterator, int patientIterator)
        {
            return @"/*[local-name()='X12_00401_837_I' and namespace-uri()='http://schemas.microsoft.com/BizTalk/EDI/X12/2006']/*[local-name()='TS837Q3_2000A_Loop' and namespace-uri()='http://schemas.microsoft.com/BizTalk/EDI/X12/2006'][" + billingIterator + "]/*[local-name()='TS837Q3_2000B_Loop' and namespace-uri()='http://schemas.microsoft.com/BizTalk/EDI/X12/2006'][" + subscriberIterator + "]/*[local-name()='TS837Q3_2000C_Loop' and namespace-uri()='http://schemas.microsoft.com/BizTalk/EDI/X12/2006'][" + patientIterator + "]/*[local-name()='TS837Q3_2300_Loop' and namespace-uri()='http://schemas.microsoft.com/BizTalk/EDI/X12/2006']";
        }
        internal static string getXPathToPatientHL04(int subscriberIterator, int billingIterator, int patientIterator)
        {
            return @"/*[local-name()='X12_00401_837_I' and namespace-uri()='http://schemas.microsoft.com/BizTalk/EDI/X12/2006']/*[local-name()='TS837Q3_2000A_Loop' and namespace-uri()='http://schemas.microsoft.com/BizTalk/EDI/X12/2006'][" + billingIterator + "]/*[local-name()='TS837Q3_2000B_Loop' and namespace-uri()='http://schemas.microsoft.com/BizTalk/EDI/X12/2006'][" + subscriberIterator + "]/*[local-name()='TS837Q3_2000C_Loop' and namespace-uri()='http://schemas.microsoft.com/BizTalk/EDI/X12/2006'][" + patientIterator + "]/*[local-name()='HL_PatientHierarchicalLevel_TS837Q3_2000C' and namespace-uri()='http://schemas.microsoft.com/BizTalk/EDI/X12/2006']/*[local-name()='HL04__HierarchicalChildCode' and namespace-uri()='']";
        }


        public static void RemoveEmptySubscribers(XmlDocument document)
        {
            //We need an array list to hold the items we want to remove.  If we remove them inline our iterators get reset.
            ArrayList _removeBillingToProviders = new ArrayList();    
            ArrayList _removeSubscribers = new ArrayList();
                ArrayList _removePatients = new ArrayList();
                

            int i = 1;
            //2000A Loop
            string XPathToBillingLoop = @"/*[local-name()='X12_00401_837_I' and namespace-uri()='http://schemas.microsoft.com/BizTalk/EDI/X12/2006']/*[local-name()='TS837Q3_2000A_Loop' and namespace-uri()='http://schemas.microsoft.com/BizTalk/EDI/X12/2006']";
            
            int billingIteratorID = 0;
            int subscriberIteratorID = 0;
            int patientIteratorID = 0;

            //Get ParentBilling Loop Nodes
            XmlNodeList _n0 = document.SelectNodes(XPathToBillingLoop);
            
            //Loop through nodes in 2000A Loop
            for (int billingID = 0; billingID < _n0.Count; billingID++)
            {
                bool removeBillingPayToProviderLoop = false;
                //Get the Subscriber Loop Nodes
                billingIteratorID = billingID + 1;

                XmlNodeList _n1 = _n0[billingID].SelectNodes(getXPathToSubscriberLoop(billingIteratorID));
                                
                for (int subID = 0; subID < _n1.Count; subID++)
                {
                    bool removeSubscriber = false;
                    bool subscriberChildren = false;
                    

                    //Are there any claims under this subscriber?
                    //XPATH is 1 based arrays
                    subscriberIteratorID = subID + 1;
                    int subscriberClaims = _n1[subID].SelectNodes(getXPathToSubscriberClaims(subscriberIteratorID,billingIteratorID)).Count;

                    if (subscriberClaims == 0)
                    {
                        removeSubscriber = true;
                        subscriberChildren = false;
                    }
                    
                    //Get the Patient Loop Nodes
                    XmlNodeList _n2 = _n1[subID].SelectNodes(getXPathToPatientLoop(subscriberIteratorID,billingIteratorID));
                    if (_n2.Count > 0)
                    {
                        _n1[subID].SelectSingleNode(getXPathToSubscriberHL04(subscriberIteratorID, billingIteratorID)).InnerText = "1";
                    }
                    else
                    {
                        _n1[subID].SelectSingleNode(getXPathToSubscriberHL04(subscriberIteratorID, billingIteratorID)).InnerText = "0";
                    }

                    for (int patID = 0; patID < _n2.Count; patID++)
                    {
                        bool removePatient = false;
                        patientIteratorID = patID + 1;
                        int patientClaims = _n2[patID].SelectNodes(getXPathToPatientClaims(subscriberIteratorID,billingIteratorID, patientIteratorID)).Count;
                        if (patientClaims == 0)
                        {
                            removeSubscriber = true;
                            removePatient = true;
                        }
                        else
                        {
                            removeSubscriber = false;
                        }
                        if (removePatient)
                        {
                            _removePatients.Add(_n2[patID]);

                        }
                    }
                   
                    if (removeSubscriber)
                    {
                        _removeSubscribers.Add(_n1[subID]);                        
                    }
                }
            }
            //First remove patients
            foreach (XmlNode node in _removePatients)
            {
                node.ParentNode.RemoveChild(node);
            }
            //Then remove subscribers
            foreach (XmlNode node in _removeSubscribers)
            {
                node.ParentNode.RemoveChild(node);
            }
            //We now need to remove any orphaned 200A BillingToPayer loops.
            RemoveEmptyBillingToPayer2000ALoops(document);
        }
        internal static void RemoveEmptyBillingToPayer2000ALoops(XmlDocument document)
        {
            //We need an array list to hold the items we want to remove.  If we remove them inline our iterators get reset.
            ArrayList _removeBillingToProviders = new ArrayList();
            

            int i = 1;
            //2000A Loop
            string XPathToBillingLoop = @"/*[local-name()='X12_00401_837_I' and namespace-uri()='http://schemas.microsoft.com/BizTalk/EDI/X12/2006']/*[local-name()='TS837Q3_2000A_Loop' and namespace-uri()='http://schemas.microsoft.com/BizTalk/EDI/X12/2006']";

            int billingIteratorID = 0;
            
            //Get ParentBilling Loop Nodes
            XmlNodeList _n0 = document.SelectNodes(XPathToBillingLoop);

            //Loop through nodes in 2000A Loop
            for (int billingID = 0; billingID < _n0.Count; billingID++)
            {
                //Get the Subscriber Loop Nodes
                billingIteratorID = billingID + 1;

                XmlNodeList _n1 = _n0[billingID].SelectNodes(getXPathToSubscriberLoop(billingIteratorID));
                if (_n1.Count == 0)
                {
                    _removeBillingToProviders.Add(_n0[billingID]);
                }
            }
            //Remove the Empty Payer
            foreach (XmlNode node in _removeBillingToProviders)
            {
                node.ParentNode.RemoveChild(node);
            }

        }

    }
}
